package com.ponhu.ea2.stockcenter.provider.service.entity.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ponhu.ea2.stockcenter.dto.WMSInventoryInfo;
import com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum;
import com.ponhu.ea2.stockcenter.provider.constants.CommonConstant;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryReal;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryUnreal;
import com.ponhu.ea2.stockcenter.provider.mapper.StockInventoryRealMapper;
import com.ponhu.ea2.stockcenter.provider.service.entity.StockInventoryRealService;
import com.ponhu.ea2.stockcenter.provider.service.entity.StockInventoryUnrealService;
import com.ponhu.ea2.stockcenter.provider.support.vo.GoodsCenterInventoryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum.TRANSFER_PLAN_IN;
import static com.ponhu.ea2.stockcenter.enums.ExchangeActionTypeEnum.TRANSFER_PLAN_OUT;
import static com.ponhu.ea2.stockcenter.provider.constants.CommonConstant.INIT_STATUS.FINISHED;
import static com.ponhu.ea2.stockcenter.provider.constants.CommonConstant.INIT_STATUS.UNFINISHED;

/**
 * 销售库存表服务实现类
 */
@Service
public class StockInventoryRealServiceImpl
        extends ServiceImpl<StockInventoryRealMapper, StockInventoryReal>
        implements StockInventoryRealService {

    @Autowired
    private StockInventoryRealMapper stockInventoryRealMapper;
    @Autowired
    private StockInventoryUnrealService stockInventoryUnrealService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<StockInventoryReal> getRealInventoryStockListIfNullCreate(Collection<String> inventoryCodeList) {
        List<StockInventoryReal> realList = this.getRealInventoryStockList(inventoryCodeList);
        //数量相等，那么直接返回
        if (realList.size() == inventoryCodeList.size()) {
            return realList;
        }

        //找不到的货品编码列表
        List<String> emptyInventoryCodeList = new ArrayList<>();
        for (String inventoryCode : inventoryCodeList) {
            StockInventoryReal inventoryReal = realList.stream().filter(f -> f.getInventoryCode().equals(inventoryCode)).findFirst().orElse(null);
            if (inventoryReal == null) {
                emptyInventoryCodeList.add(inventoryCode);
            }
        }

        //查看是否有未初始化的货品，如果有那么更新成已完成
        List<StockInventoryReal> unFinishedRealInventoryList = this.list(Wrappers.lambdaQuery(StockInventoryReal.class)
                .eq(StockInventoryReal::getStatus, UNFINISHED)
                .in(StockInventoryReal::getInventoryCode, emptyInventoryCodeList));

        List<StockInventoryUnreal> unFinishedUnRealInventoryList = stockInventoryUnrealService.list(Wrappers.lambdaQuery(StockInventoryUnreal.class)
                .eq(StockInventoryUnreal::getStatus, UNFINISHED)
                .in(StockInventoryUnreal::getInventoryCode, emptyInventoryCodeList));

        List<String> insertInventoryCodeList = null;
        if (CollectionUtils.isNotEmpty(unFinishedRealInventoryList)) {


            List<StockInventoryReal> realStream = unFinishedRealInventoryList.stream().map(i -> i.setStatus(FINISHED)).collect(Collectors.toList());
            List<StockInventoryUnreal> unRealStream = unFinishedUnRealInventoryList.stream().map(i -> i.setStatus(FINISHED)).collect(Collectors.toList());

            //更新实物类化货品
            this.updateBatchById(realStream);
            if (CollectionUtils.isNotEmpty(unRealStream)) {
                //更新虚拟类货品
                stockInventoryUnrealService.updateBatchById(unRealStream);
            }
        }

        insertInventoryCodeList = emptyInventoryCodeList.stream().filter(code ->
                        unFinishedRealInventoryList.stream().noneMatch(f -> f.getInventoryCode().equals(code)))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(insertInventoryCodeList)) {
            return this.getRealInventoryStockList(inventoryCodeList);
        }

        //商品中心查到的货品数据
        List<GoodsCenterInventoryVO> inventoryList = stockInventoryRealMapper.getInventoryByInventoryCodeList(insertInventoryCodeList);
        //商品中心未查到，那么直接返回
        if (CollectionUtils.isEmpty(inventoryList)) {
            return this.getRealInventoryStockList(inventoryCodeList);
        }

        //虚拟类货品列表
        List<StockInventoryUnreal> unrealList = new ArrayList<>();

        List<StockInventoryReal> collect = inventoryList.stream().map(i -> {
                    StockInventoryReal stockInventoryReal = new StockInventoryReal()
                            .setInventoryId(i.getInventoryId())
                            .setInventoryCode(i.getInventoryCode())
                            .setGoodsId(i.getGoodsId())
                            .setSaleStockNum(CommonConstant.ZERO)
                            .setUsedStockNum(CommonConstant.ZERO)
                            .setStatus(FINISHED);

                    if (!i.isReal()) {
                        StockInventoryUnreal stockInventoryUnReal = new StockInventoryUnreal()
                                .setInventoryId(i.getInventoryId())
                                .setInventoryCode(i.getInventoryCode())
                                .setGoodsId(i.getGoodsId())
                                .setSaleStockNum(CommonConstant.ZERO)
                                .setStatus(FINISHED);
                        unrealList.add(stockInventoryUnReal);
                    }
                    return stockInventoryReal;
                }

        ).collect(Collectors.toList());

        //插入实物类货品
        if (CollectionUtils.isNotEmpty(collect)) {


            List<StockInventoryReal> existsRealList = this.list(Wrappers.lambdaQuery(StockInventoryReal.class).in(StockInventoryReal::getInventoryCode, collect.stream().map(StockInventoryReal::getInventoryCode).collect(Collectors.toList())));
            List<String> realInventoryCodeList = existsRealList.stream().map(StockInventoryReal::getInventoryCode).collect(Collectors.toList());

            List<StockInventoryReal> saveRealList = collect.stream().filter(f -> !realInventoryCodeList.contains(f.getInventoryCode())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(saveRealList)) {
                this.saveBatch(saveRealList);
            }
        }

        if (CollectionUtils.isNotEmpty(unrealList)) {
            //插入虚拟类货品
            List<StockInventoryUnreal> existsUnRealList = stockInventoryUnrealService.list(Wrappers.lambdaQuery(StockInventoryUnreal.class).in(StockInventoryUnreal::getInventoryCode, unrealList.stream().map(StockInventoryUnreal::getInventoryCode).collect(Collectors.toList())));
            List<String> unRealInventoryCodeList = existsUnRealList.stream().map(StockInventoryUnreal::getInventoryCode).collect(Collectors.toList());

            List<StockInventoryUnreal> saveUnRealList = unrealList.stream().filter(f -> !unRealInventoryCodeList.contains(f.getInventoryCode())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(saveUnRealList)) {
                stockInventoryUnrealService.saveBatch(saveUnRealList);
            }
        }

        return this.getRealInventoryStockList(inventoryCodeList);
    }

    @Override
    public List<StockInventoryReal> getRealInventoryStockList(Collection<String> inventoryCodeList) {
        return this.list(
                Wrappers.lambdaQuery(StockInventoryReal.class)
                        .eq(StockInventoryReal::getStatus, FINISHED)
                        .in(StockInventoryReal::getInventoryCode, inventoryCodeList));
    }

    @Override
    public boolean createAndInitStockData(Long goodsId, Long inventoryId, String inventoryCode, int stockNumber) {
        inventoryCode = inventoryCode.trim();
        //判断是否存在，如果已经存在那么直接返回成功
        StockInventoryReal inventory = this.getOne(Wrappers.lambdaQuery(StockInventoryReal.class)
                .eq(StockInventoryReal::getGoodsId, goodsId)
                .eq(StockInventoryReal::getInventoryId, inventoryId)
                .eq(StockInventoryReal::getInventoryCode, inventoryCode));
        if (inventory != null) {
            return true;
        }

        //不存在那么插入新数据
        StockInventoryReal stockInventoryReal = new StockInventoryReal();
        stockInventoryReal.setInventoryId(inventoryId)
                .setGoodsId(goodsId)
                .setInventoryCode(inventoryCode)
                .setSaleStockNum(stockNumber)
                .setUsedStockNum(0)
                .setStatus(FINISHED);
        return this.save(stockInventoryReal);
    }

    /**
     * 修改货品在途库存数量
     *
     * @param inventoryInfoList
     * @param actionType
     * @return
     */
    @Override
    public boolean updateFreeStockNum(List<WMSInventoryInfo> inventoryInfoList, ExchangeActionTypeEnum actionType) {

        Map<String, Integer> wmsMap = inventoryInfoList.parallelStream()
                .collect(Collectors.toMap(WMSInventoryInfo::getInventoryCode, WMSInventoryInfo::getInventoryQuantityAbs));

        List<String> inventoryCodes = inventoryInfoList.parallelStream()
                .map(WMSInventoryInfo::getInventoryCode).collect(Collectors.toList());
        LambdaQueryWrapper<StockInventoryReal> queryWrapper = Wrappers
                .lambdaQuery(StockInventoryReal.class)
                .in(StockInventoryReal::getInventoryCode, inventoryCodes);

        List<StockInventoryReal> stockInventoryReals = list(queryWrapper).parallelStream().map(stock -> {
            if (actionType == TRANSFER_PLAN_OUT)
                return stock.setFreeStockNum(stock.getFreeStockNum() + wmsMap.get(stock.getInventoryCode()));
            if (actionType == TRANSFER_PLAN_IN)
                return stock.setFreeStockNum(stock.getFreeStockNum() - wmsMap.get(stock.getInventoryCode()));
            return stock;
        }).collect(Collectors.toList());

        return saveOrUpdateBatch(stockInventoryReals);
    }

}




